package ticketingsystem;



//import java.util.concurrent.atomic.AtomicLong;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
public class Train {
    private int ncoach;
    private int nseat;
    private int nstation;

    private int perseat;

    private long[] seat;

    private final ReadWriteLock RwLock=new ReentrantReadWriteLock(true);

    public Train(int coachnum, int seatnum, int stationnum){
        nseat = coachnum * seatnum;
        ncoach = coachnum;
        nstation = stationnum;
        perseat = seatnum;

        seat = new long[nseat];
/*
        for(int i = 0; i < nseat; i++){
            seat[i] = new long(0);
        }
        */
    }
/*
    public int[] buy(int departure,int arrival)
    {
        int period = arrival - departure;
        long mask = ((1 << period)-1) << departure;

        for(int i = 0; i < nseat;i++)
        {
            long oldStatus = seat[i].get();
            while((mask & oldStatus) == 0)
            {
                if(seat[i].compareAndSet(oldStatus,oldStatus|mask))
                    return new int[] { i / perseat + 1, i % perseat + 1 };
                oldStatus = seat[i].get();
            }
        }
        return null;
    }
    */
    public int[] buy(int departure,int arrival)
    {
        int period = arrival - departure;
        long mask = ((1 << period)-1) << departure;
        RwLock.writeLock().lock();
        for(int i = 0; i < nseat;i++)
        {
            long oldStatus = seat[i];
            if((mask & oldStatus) == 0)
            {
                //if(seat[i].compareAndSet(oldStatus,oldStatus|mask))
                
                seat[i] = oldStatus|mask;
                RwLock.writeLock().unlock();
                return new int[] { i / perseat + 1, i % perseat + 1 };
            }
        }
        RwLock.writeLock().unlock();
        return null;
    }
/*
    public boolean refund(int coach,int cseat,int departure,int arrival)
    {
        int period = arrival - departure;
        long mask = ((1 << period)-1) << departure;
        int seatid = (coach - 1) * perseat + cseat - 1;
        while(true) {
            long oldStatus = seat[seatid].get();
            if (seat[seatid].compareAndSet(oldStatus, (oldStatus & ~mask)))
                return true;
        }
    }
    */
    public boolean refund(int coach,int cseat,int departure,int arrival)
    {
        int period = arrival - departure;
        long mask = ((1 << period)-1) << departure;
        int seatid = (coach - 1) * perseat + cseat - 1;
        RwLock.writeLock().lock();
        long oldStatus = seat[seatid];
        //if (seat[seatid].compareAndSet(oldStatus, (oldStatus & ~mask)))
        seat[seatid] = oldStatus & ~mask;
        RwLock.writeLock().unlock();
        return true;
    }
    /*
    public int query(int departure,int arrival)
    {
        int period = arrival - departure;
        long mask = ((1 << period)-1) << departure;
        int count = 0;
        for(int i = 0;i < nseat; i++)
        {
            long status = seat[i].get();
            if((mask & status) == 0)
                count ++;
        }
        return count;
    }
    */
    public int query(int departure,int arrival)
    {
        int period = arrival - departure;
        long mask = ((1 << period)-1) << departure;
        int count = 0;
        RwLock.readLock().lock();
        for(int i = 0;i < nseat; i++)
        {
            long status = seat[i];
            if((mask & status) == 0)
                count ++;
        }
        RwLock.readLock().unlock();
        return count;
    }
}
